package miniBanco.Mapper;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Locale;

import basics.DBManager;
import miniBanco.Core.Cliente;
import miniBanco.Core.Cuenta;
import miniBanco.Core.DomainObject;
import miniBanco.Core.Moneda;
import miniBanco.Core.Movimiento;
import miniBanco.Core.TipoCuenta;
import miniBanco.Mapper.Interface.ICuentaFinder;
import miniBanco.Mapper.Interface.IstatementSource;

public class CuentaMapper extends AbstractMapper implements ICuentaFinder {
	private static final String TAG = CuentaMapper.class.getSimpleName();
	public static final String IDCOLUMN = "id";
	public static final String COLUMNS = "idCliente,Moneda,Cbu,Saldo,TipoCuenta,Activa";

	@Override
	protected StringBuilder findStatement() {
		StringBuilder sb = new StringBuilder();
		sb.append("SELECT "+IDCOLUMN+","+COLUMNS+
				" FROM "+ getTableName()+
				" WHERE id = %d ");
		return sb;
	}

	public void findAllFor(Cliente cliente) throws SQLException {
		String sql = String.format(findForCliente().toString(), cliente.getNroCliente());
		ResultSet rs = sqlHelper.ExecuteQuery(sql, TAG);

		while(rs.next())
		{
			Cuenta cuenta = (Cuenta)load(rs);
			cliente.AgregarCuenta(cuenta);
			DBManager.Log(TAG,"Load Cuenta||ID:"+cuenta.getID()+"||cbu:"+cuenta.getNroCuenta()+"||Cliente:"+cliente.getNombre());
		}
	}
	
	@Override
	protected DomainObject doLoad(long id, ResultSet rs) throws SQLException {
		id = rs.getLong(1);

		int pmoneda = rs.getInt(3);
		int cbu = rs.getInt(4);
		int saldo = rs.getInt(5);
		int activa = rs.getInt(7);
		int ptipoCuenta = rs.getInt(6);
		
		Moneda moneda = mapperRegistry.MonedaDao().getByTipo(pmoneda);
		TipoCuenta tipoCuenta = mapperRegistry.TipoCuentaDao().getByTipoCuenta(ptipoCuenta);
		Cuenta cuenta = new Cuenta(moneda,cbu,tipoCuenta);
		cuenta.setID(id);
		

		
		
		if(activa == 1)
			cuenta.Activar();
		else
			cuenta.Desactivar();
		
		cuenta.setSaldo(saldo);
		mapperRegistry.MovimientoMapper().findAllFor(cuenta);
		return cuenta;
	}
	
	@Override
	protected StringBuilder doInsert(DomainObject subject) {
		Cuenta cuenta = (Cuenta) subject;
		String insertStatment = "INSERT INTO "+getTableName()+" ("+COLUMNS+")  VALUES ( %d,%d,%d,%.2f,%d,1) ";
		insertStatment = String.format(Locale.US,insertStatment, cuenta.getCliente().getNroCliente(),
		cuenta.getMoneda().getValue(),
		cuenta.getNroCuenta(),
	    cuenta.getSaldo(),
	    cuenta.getTipoCuenta().getValue());
			
		StringBuilder sb = new StringBuilder();
		sb.append(insertStatment);
		return sb;
	}

	@Override
	protected String getTableName() {
		return "ClienteCuenta";
	}

	@Override
	public Cuenta find(long id) {
		return (Cuenta) abstractFind(id);
	}


	@SuppressWarnings("unchecked")
	public ArrayList<Cuenta> FindByCbu(int cbu) {
		return (ArrayList<Cuenta>) findMany(new FindByCbu(cbu));
	}	
	
	static class FindByNroCliente implements IstatementSource
	{
		long nroCliente;
		public FindByNroCliente(int nroCliente)
		{
			this.nroCliente = nroCliente;
		}
		@Override
		public String sql() {
			return findForCliente();
		}

		@Override
		public Object[] parameters() {
			Object[] result = {nroCliente};
			return result;
		}
	}
	
	static class FindByCbu implements IstatementSource
	{
		int cbu;
		public FindByCbu(int cbu)
		{
			this.cbu = cbu;
		}
		@Override
		public String sql() {
			return findByNroCuenta();
		}

		@Override
		public Object[] parameters() {
			Object[] result = {cbu};
			return result;
		}
	}
 
	private static String findByNroCuenta()
	{
		String sql= "SELECT "+IDCOLUMN+","+COLUMNS+
				" FROM ClienteCuenta"+
				" WHERE Cbu = %d and Activa = 1";
		return sql;
	}
	 
	 private static String findForCliente()
	{
		String sql= "SELECT "+IDCOLUMN+","+COLUMNS+
				" FROM ClienteCuenta"+
				" WHERE idCliente = %d and Activa = 1";
		return sql;
	}

	@Override
	public void doSave(DomainObject subject) {
		Cuenta cuenta = (Cuenta) subject;
		for(Movimiento movimiento:cuenta.getMovimientos()){
			mapperRegistry.MovimientoMapper().doSave(movimiento);
		}
		save(cuenta);
	}
	public void doDelete(DomainObject subject) {
		Cuenta cuenta = (Cuenta) subject;
		for(Movimiento movimiento:cuenta.getMovimientos()){
			mapperRegistry.MovimientoMapper().delete(movimiento);
		}
		delete(cuenta);
	}

	@Override
	protected StringBuilder doUpdate(DomainObject subject) {
		Cuenta cuenta = (Cuenta) subject;
		StringBuilder sb = new StringBuilder();
		String sFloat = Float.toString(cuenta.getSaldo());
		sb.append("UPDATE "+getTableName()+" SET Saldo = "+sFloat+", "
				+ "Activa = "+cuenta.getEstado()+""
			    + " Where ID="+subject.getID());
		return sb;
	}

}
